﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Net.Sockets;
using System.Net;

namespace ServCSS.ServCSS.Server
{
    class CServer
    {
        public CServer_Datos data;
        int contByte;

        //Start
        public CServer(string hosting, int puerto, int maxCon, int minCon, int[] reservPort)
        {
            data = new CServer_Datos();

            data.direccionIP = IPAddress.Parse(hosting);
            data.puertoPrincipal = puerto;
            data.puertoReservado = reservPort;

            IPEndPoint endPoint = new IPEndPoint(data.direccionIP, data.puertoPrincipal);
            data.SockPrincipal = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

            data.SockPrincipal.Bind(endPoint);

            data.minCOn = minCon;
            data.maxCon = maxCon;
            data.totCon = 0;

            data.SockCliente = new Socket[maxCon];

            data.paqByte = new byte[maxCon][];
            for (int i = 0; i < data.maxCon; i++)
            {
                data.paqByte[i] = new byte[1024];
            }
        }

        //Running en espera y gestoria de conexiones
        public void RunCon()
        {
            try
            {
                data.SockPrincipal.Listen(data.maxCon);

                Console.WriteLine("srv_root: Activado Hilo de espera de Conexiones");

                Socket sockBuff;
                byte[] buffByte = new byte[1024];
                CPaq_Genric paq_generic = new CPaq_Genric();
                CPaq_Asignacion paq_asig = new CPaq_Asignacion();
                IPEndPoint endPoint;
                while (data.totCon < data.maxCon)
                {
                    //otengo el socket de conexion con el cliente
                    sockBuff = data.SockPrincipal.Accept();
                    sockBuff.Receive(buffByte);

                    paq_generic = (CPaq_Genric) CSRepositor.Desempaquetar(buffByte);

                    if(paq_generic.ID == -1 && paq_generic.peticion == "Conectar")
                    {
                        Console.WriteLine("srv_root: Procesando peticion de conexion con :" + sockBuff.RemoteEndPoint.ToString());
                        
                        //creamos nuevo socket para escuchar a ese cliente en particular
                        //y le damos los datos para que se conecte a el

                        //en este caso, el server seguira siempre igual, solo cambia el puerto
                        paq_asig.nuevoID = data.totCon;
                        paq_asig.nuevoPuerto = data.puertoReservado[data.totCon];
                        paq_asig.nuevoServer = data.direccionIP;

                        buffByte = CSRepositor.Empaquetar((object) paq_asig);

                        //iniciamos el nuevo socket para la conexion
                        data.SockCliente[data.totCon] = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);
                        //creamos el nuevo endpoint
                        endPoint = new IPEndPoint(data.direccionIP, data.puertoReservado[data.totCon]);
                        
                        data.SockCliente[data.totCon].Bind(endPoint);                                                
                        contByte = sockBuff.Send(buffByte);
                        Console.WriteLine("srv_root: Enviando nuevos datos de conexion al cliente: " + sockBuff.RemoteEndPoint.ToString());
                        //esperamos OK del nuevo Sock y lo limitamos a una peticion a la ves
                        data.SockCliente[data.totCon].Listen(1);
                        sockBuff = data.SockCliente[data.totCon].Accept();
                        Console.WriteLine("Srv_root: Esperando OK! de los datos");
                        sockBuff.Receive(buffByte);

                        paq_generic = (CPaq_Genric) CSRepositor.Desempaquetar(buffByte);

                        Console.WriteLine("srv_root: ->Respuesta: " + paq_generic.peticion);
                    }
                    else
                    {
                        Console.WriteLine("srv_root: Denegado intento de conexion con :" + sockBuff.AddressFamily.ToString());
                    }

                }

                Console.WriteLine("srv_root: Alcanzado limite de Conexion");
            }
            catch (Exception e)
            {
                Console.WriteLine("svr_root: ERROR" + e.ToString());
            }
        }
    }
}
